﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExaminationTT.Rule;
using ExaminationTT.Model;

namespace ConcreteRules
{
    public class StudentsConflitRule : IRule
    {

        #region IRule Members

        public IConflict EnforceRule(IExam exam1, IExam exam2)
        {
            if (exam1.ExamDate >= exam2.ExamDate && exam1.ExamDate <= exam2.ExamEndDate // data de inicio do exam1 intersecta o exam2
                || exam1.ExamEndDate >= exam2.ExamDate && exam1.ExamEndDate <= exam2.ExamEndDate // data de fim do exam1 intersecta o exam2
                || exam1.ExamDate <= exam2.ExamDate && exam1.ExamEndDate >= exam2.ExamEndDate //exam 1 sobrepoe exam 2
                || exam2.ExamDate <= exam1.ExamDate && exam2.ExamEndDate >= exam1.ExamEndDate //exam 2 sobrepoe exam 1
                )
            {
                IEnumerable<ISubscription> subs = exam1.CUnit.Subscriptions.Intersect(exam2.CUnit.Subscriptions, new ExamIntersectComparator());
                if (subs.Count() > 0)
                {
                    List<IStudent> std = new List<IStudent>();
                    foreach (var item in subs)
                    {
                        std.Add(item.Student);
                    }
                    return new StudentsConflitConflit(this, exam1, exam2, subs);
                }
            }
            return null;
        }

        public string Name
        {
            get { return "Regra que avalia os alunos com exames marcados na mesma hora"; }
        }

        #endregion

        private class StudentsConflitConflit : IConflict
        {
            
            public StudentsConflitConflit(StudentsConflitRule rule, IExam exam1, IExam exam2, IEnumerable<ISubscription> subs)
            {
                _exams = new List<IExam>();
                _exams.AddRange(new []{exam1, exam2});
                _rule = rule;
                _affectedStudents = new StudentsEnumerable(subs);
                _affectedStudentsCount = _affectedStudents.Count();
               
            }

            #region IConflit Members

            private List<IExam> _exams;
            private StudentsConflitRule _rule;
            private StudentsEnumerable _affectedStudents;
            private int _affectedStudentsCount;
            public IEnumerable<IExam> Exams
            {
                get { return _exams.ToArray(); }
            }

            public string ConflictType
            {
                get { return "Estudantes com 2 exames à mesma hora"; }
            }

            public string ConflitcInfo
            {
                get
                { 
                    
                    return String.Format("O exame de {0} e {1} estão marcados para horas que se intersectam. Existem {2} estudantes em conflito",
                    _exams[0].CUnit.Acronym, _exams[1].CUnit.Acronym, _affectedStudentsCount);
                }
            }

            public string RuleName
            {
                get { return _rule.Name; }
            }

            public ConflictWeight Weight
            {
                get { return ConflictWeight.Minimal; }
            }

            public IEnumerable<IStudent> AffectedStudents
            {
                get
                {
                    return _affectedStudents;
                }
            }
            public int AffectedStudentsCount
            {
                get { return _affectedStudentsCount; }
            }

            #endregion
        }
        private class ExamIntersectComparator : IEqualityComparer<ISubscription>
        {
            #region IEqualityComparer<ISubscription> Members

            public bool Equals(ISubscription x, ISubscription y)
            {
                return x.Student.Equals(y.Student);
            }

            public int GetHashCode(ISubscription obj)
            {
                return this.GetHashCode();
            }

            #endregion
        }

    }

    
}
